<template>
    <div :id="tableId" class="dzs-table-wrop">
        <div class="list-wrop">
            <el-table :border="border" v-if="headerData.length" :data="tableData" class="table" ref="dzsTable"
                v-loading="loading" @selection-change="handleSelectionChange" :stripe="true" v-bind="{ ...tableOptions }"
                :height="tableHeight ? tableHeight : '100%'">
                <el-table-column type="selection" width="55" v-if="showCheckbox"></el-table-column>
                <template v-for="(option) in headerData">
                    <el-table-column v-if="!option.isSlot" :label="option.label" :width="option.width" :prop="option.key"
                        :class-name="'table-column_' + columnClassName" v-bind="{ ...option.props }">
                    </el-table-column>
                    <el-table-column v-else :class-name="'table-column_' + columnClassName" :label="option.label"
                        :width="option.width" v-bind="{ ...option.props }">
                        <template #default="scope">
                            <slot :name="option.key" :row="{ ...scope.row }"></slot>
                        </template>
                    </el-table-column>
                </template>
                <el-table-column v-if="showOperation" :class-name="'table-column_' + columnClassName"
                    v-bind="{ ...operationOption }" label="操作">
                    <template #default="scope">
                        <dzs-button text type="primary" @click="onEdit(scope.row)" v-if="operation.includes('edit')">
                            编辑
                        </dzs-button>
                        <dzs-button text type="primary" @click="onDetails(scope.row)" v-if="operation.includes('detail')">
                            详情
                        </dzs-button>
                        <dzs-button text type="primary" @click="onDel(scope.row)" v-if="operation.includes('delete')">
                            删除
                        </dzs-button>
                        <slot name="button" :row="{ ...scope.row }"></slot>
                    </template>
                </el-table-column>
            </el-table>
            <div class="sider-box" v-if="headerData.length">
                <dzs-tabel-sider :border="border" :treeProps="tableOptions['tree-props']" v-if="showSider" :column="tableHeader"
                    :list="tableData" @change="onSiderChange" @changeHeight="changeHeight" @search="siderSearch"
                    :forceSearch="forceSearch" :show-siders="showSiders"></dzs-tabel-sider>
            </div>
            <div class="table-empty" :style="{ height: tableHeight ? tableHeight : '100%' }" v-if="!headerData.length">
                你还没设置数据显示
            </div>
        </div>
        <div :class="['table-footer', footerPosition]" v-if="(total > maxSize) && showPage">
            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
                :page-sizes="[maxSize, maxSize * 2, maxSize * 4]" v-bind="{ ...paginationSet }" :total="total">
            </el-pagination>
        </div>
    </div>
</template>
<script setup lang="ts">
/**
 * @name 表格组件
 * @props operation 操作数据 edit 编辑 details 详情 del 删除
 * @props tableHeader 表头数据及表单key  label 表头名称  key 关键字/slot的name width 宽度 isSlot:自定义slot props:el-table-column的配置项
 * @props showCheckbox 是否显示多选 默认 false 不显示  true 显示
 * @props maxSize 每页显示条数 默认10
 * @props showPage 是否显示分页 默认true 显示
 * @props operationOption 操作列配置项
 * @props list 表格数据
 * @props total 总条数
 * @props tableOptions 饿了吗ui的配置
 * @props loading 是否开启加载中 可以在 tableOptions配置自己想要的加载 element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading"
 * @props height 高度
 * @props showSider 是否显示侧边栏 默认true 显示
 * @props showOperation 是否显示操作列 默认true 显示
 * @props forceSearch 是否强制搜索 默认false 不强制搜索 true 强制搜索
 *
 * @methods selectionChange 选中数据改变 返回当前选中的数据
 * @methods change 页码/条数改变 返回当前页码/条数  status:page 改变页码  status:size 改变条数
 * @methods change 列表数据改变 返回当前改变的数据  status:delete 删除数据  status:edit 编辑数据 status:details 详情数据
 * @methods onEdit 编辑
 * @methods onDetails 详情
 * @methods onDelete 删除
 * @methods setSelection 设置选中的数据
 * @methods getTableMethods 获取到原生方法
 * @methods sizeChange 选择条数改变
 * @methods currentChange 页码改变
 * 
 * @slot button 操作列按钮
 *
 */

import { ref, watch, computed, onMounted, defineExpose } from 'vue';
import defaultProps from './props';
import dzsTabelSider from "./sider/index.vue";
import type { TableHeader } from "./@types";
import tool from "@/utils";
import { ElTable } from 'element-plus'

const props = defineProps(defaultProps);
const paginationSet = ref<Record<string, any>>({
    background: false,
    layout: "total, sizes, prev, pager, next, jumper",
});
const headerData = ref<TableHeader[]>([]);
const columnClassName = ref("");
const tableData = ref<Array<Record<string, any>>>([]);
const tableId = ref(`dzsTable${new Date().getTime()}`);
const dzsTableByElTable = ref<InstanceType<typeof ElTable>>();

/**监听table-header数据变化*/
watch(() => props.tableHeader, (newVal) => {
    headerData.value = tool.deepCopy(newVal);
}, {
    deep: true,
    immediate: true,
})

/**监听list数据变化*/
watch(() => props.list, (newVal) => {
    tableData.value = tool.deepCopy(newVal);
}, {
    deep: true,
    immediate: true,
})

/**计算表格高度*/
const tableHeight = computed(() => {
    let height = props.height;
    if (height && typeof height === "string") {
        return height;
    }
    return height ? `${height}px` : "";
})

const emit = defineEmits([
    "selectionChange",
    "change",
    "onEdit",
    "onDetails",
    "onDelete",
    "onChange",
    "sizeChange",
    "currentChange",
    "onSiderChange",
    "heightChange",
    "siderSearch",
    "onFormBoxWidthChange",
    'onPageChange'
])

onMounted(() => {
    listenFormBoxWidth();
})

/**选择条数改变*/
const handleSizeChange = (num: number): void => {
    onPageChange("size", '选择条数改变', num);
    onChange("size", "选择条数改变", num)
    emit("sizeChange", num);
}
/**页码改变*/
const handleCurrentChange = (num: number): void => {
    onChange("page", "页码改变", num);
    onPageChange("page", '页码改变', num);
    emit("currentChange", num);
}
/**编辑*/
const onEdit = (item: Record<string, any>): void => {
    onChange("edit", "编辑", item);
    emit("onEdit", item);
}
/**详情*/
const onDetails = (item: Record<string, any>): void => {
    onChange("details", "详情", item);
    emit("onDetails", item);
}
/**删除*/
const onDel = (item: Record<string, any>): void => {
    onChange("delete", "删除", item);
    emit("onDelete", item);
}
/**改变事件*/
const onChange = (status: string, title: string, data: Record<string, any> | number): void => {
    let obj = { status: status, title: title, data: data, size : data };
    emit("change", obj);
    emit("onChange", obj);
}

/**分页改变事件*/
const onPageChange = (status: string, title: string, data: number ): void => {
    emit("onPageChange",{
        data : data,
        status : status ,
        title : title
    });
} 

/**选中事件*/
const handleSelectionChange = (val: Array<Record<string, any>>) => {
    emit("selectionChange", val);
}
/**设置选中行*/
const setSelection = (rows: Array<Record<string, any>>) => {
    if (rows) {
        rows.forEach((row) => {
            dzsTableByElTable.value?.toggleRowSelection(row, true);
        });
    } else {
        dzsTableByElTable.value?.clearSelection();
    }
}
/**侧边栏改变*/
const onSiderChange = (val: TableHeader[]) => {
    headerData.value = val;
}
/**改变高度*/
const changeHeight = (e: string) => {
    columnClassName.value = e;
}
/**获取到原生方法*/
const getTableMethods = () => {
    return dzsTableByElTable
}
/**侧边栏搜索*/
const siderSearch = (list: Array<Record<string, any>>): void => {
    tableData.value = list;
}
/**监听form-box宽度变化*/
const listenFormBoxWidth = () => {
    let paginationSetPC = {
        background: false,
        layout: "total, sizes, prev, pager, next, jumper",
    }
    let paginationSetPhone = {
        background: false,
        layout: "sizes , total,  prev, next",
    }
    const resizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
            const { width } = entry.contentRect;
            paginationSet.value = width <= 768 ? paginationSetPhone : paginationSetPC;
        }
    })
    const formBox = document.querySelector(`#${tableId.value}`);
    if (!formBox) return;
    resizeObserver.observe(formBox);
}


defineExpose({
    getTableMethods,
    setSelection
})
</script>
<style scoped lang="scss">
.dzs-table-wrop {
    height: 100%;
    position: relative;

    .list-wrop {
        display: flex;
        overflow-y: scroll;
        -ms-overflow-style: none;
        /* IE 10+ */
        scrollbar-width: none;

        /* Firefox */
        &::-webkit-scrollbar {
            /* Chrome Safari */
            display: none;
        }

        :deep(.el-table__body-wrapper) {

            // 滚动条宽度
            &::-webkit-scrollbar {
                width: 4px;
                background-color: #fff;
                display: block;
            }

            // 滚动条轨道
            &::-webkit-scrollbar-track {
                background-color: transparent;
                -webkit-border-radius: 2em;
                -moz-border-radius: 2em;
                border-radius: 2em;
            }

            // 滚动条背景
            &::-webkit-scrollbar-track-piece {
                background-color: transparent;
                -webkit-border-radius: 2em;
                -moz-border-radius: 2em;
                border-radius: 2em;
            }

            // 滚动条滑块
            &::-webkit-scrollbar-thumb {
                background-color: #e9e7e7;
                -webkit-border-radius: 1em;
                -moz-border-radius: 1em;
                border-radius: 1em;
            }
        }
        :deep(.dzs-button.is-text){
            margin-left: 0px;
            padding: 8px 8px;
        }
        :deep(.el-table) {
            tr {
                .table-column_mini {
                    height: 30px;
                    padding: 0;
                }

                .table-column_middle {
                    height: 50px;
                }

                .table-column_max {
                    height: 70px;
                }
            }
        }
    }

    .table-empty {
        display: flex;
        align-items: center;
        justify-content: center;
        border: 1px solid #ebeef5;
        width: 100%;
    }

    @media screen and (max-width: 768px) {
        .table {
            height: auto;
        }
    }

    .table-footer {
        display: flex;
        padding-top: 10px;

        &.left {
            justify-content: flex-start;
        }

        &.right {
            justify-content: flex-end;
        }
    }

    @media screen and (max-width: 768px) {
        .table-footer {
            position: relative;
            bottom: 0;
            right: 0;
            z-index: 1;
            margin-top: 20px;
            padding: 20px;
            text-align: right;
            width: 100%;
            overflow-x: auto;
        }
    }

    .empty {
        text-align: center;
        padding-top: 10px;
    }


    .btn {
        margin-left: 10px;
    }
}
</style>